#include "SDragListWidget.h"

#include <core/ImageMgr.h>
#include <QPainter>

void SDragListItemDelegate::paint(QPainter* painter,
    const QStyleOptionViewItem& option,
    const QModelIndex& index) const {
  QStyledItemDelegate::paint(painter, option, index);

  SImage* img = ImgMgr::instance().image("widgets_drag_handle_right",
                                         WidgetStatus::kNormal);
  if (img) {
    int width = img->width();
    int height = img->height();

    painter->setRenderHint(QPainter::SmoothPixmapTransform);
    painter->drawImage(
        QRect(option.rect.right() - width - 4, option.rect.top() + 4, width, height), *img);
  }
}

bool SDragListItemModel::dropMimeData(const QMimeData* data,
                                      Qt::DropAction action, int row,
                                      int column, const QModelIndex& parent) {
  if (action == Qt::IgnoreAction) return true;

  if (!data->hasFormat("application/x-qabstractitemmodeldatalist"))
    return false;

  if (column > 0) return false;

  QByteArray encodedData =
      data->data("application/x-qabstractitemmodeldatalist");
  QDataStream stream(&encodedData, QIODevice::ReadOnly);

  while (!stream.atEnd()) {
    int row;
    int count;
    QMap<int, QByteArray> roleDataMap;
    stream >> row >> count >> roleDataMap;

    if (row != -1) {
      for (int i = 0; i < count; ++i) {
        QStandardItem* item = new QStandardItem();
        item->setData(roleDataMap[Qt::DisplayRole], Qt::DisplayRole);
        insertRow(row + i, item);
      }
    }
  }

  return true;
}

SDragListWidget::SDragListWidget(QWidget* parent) : QListView(parent) {
  setSelectionMode(QAbstractItemView::SingleSelection);
  setDragEnabled(true);
  setAcceptDrops(true);
  setDropIndicatorShown(true);
  setDefaultDropAction(Qt::MoveAction);
  setItemDelegate(new SDragListItemDelegate((QObject*)parent));
}

void SDragListWidget::startDrag(Qt::DropActions supportedActions) {
  QModelIndexList indexes = selectionModel()->selectedIndexes();
  if (!indexes.isEmpty()) {
    QMimeData* mimeData = model()->mimeData(indexes);
    QDrag* drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->exec(Qt::MoveAction);
  }
}

void SDragListWidget::dropEvent(QDropEvent* event) {
  if (event->mimeData()->hasFormat(
          "application/x-qabstractitemmodeldatalist")) {
    QModelIndex index = indexAt(event->pos());
    if (!index.isValid()) {
      event->ignore();
      return;
    }

    QStandardItemModel* model =
        qobject_cast<QStandardItemModel*>(this->model());
    if (!model) {
      event->ignore();
      return;
    }

    int sourceRow = currentIndex().row();
    int destRow = index.row();

    if (sourceRow != destRow) {
      QList<QStandardItem*> sourceItems = model->takeRow(sourceRow);
      model->insertRow(destRow, sourceItems);
      setCurrentIndex(model->index(destRow, 0));
    }

    event->acceptProposedAction();
  }
}

void SDragListWidget::dragEnterEvent(QDragEnterEvent* event) {
  if (event->mimeData()->hasFormat(
          "application/x-qabstractitemmodeldatalist")) {
    event->acceptProposedAction();
  }
}

void SDragListWidget::dragMoveEvent(QDragMoveEvent* event) {
  if (event->mimeData()->hasFormat(
          "application/x-qabstractitemmodeldatalist")) {
    event->acceptProposedAction();
  }
}
